Spring Cloud Aliababa Sentinel

Sentinel 是 Alibaba Spring Cloud 微服务组件之一,他以 流量为切入点,主要实现流量控制、熔断降级、系统负载保护等多个维度来保证服务的稳定性,因此他还提供了机器发现、健康情况、监控、规则管理和推送等功能,并提供了一个可视化控制页面 Sentinel Dashboard,可前往 https://github.com/alibaba/Sentinel/releases/tag/1.8.2 进行下载,之后可以通过下述命令启动(Sentinel Dashboard 的帐号密码同样都为 sentinel):

1
sudo java -Dserver.port=9899 -Dcsp.sentinel.dashboard.server=localhost:9899 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar

限流模式

直接失败

通过 postman 进行测试

直接限流

当实例运行后,进入该实例中,在控制台中的流控规则中添加一个控流规则,并设置 QPS 为 1,并选择直接控流模式,而这个规则所达到的效果就是让超过阀值的请求直接失效,因此我们需要在项目中添加所需依赖:

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在配置中我们依然只需要连接 Sentinel 控制台即可,并配置项目的名称,这将会在控制台中进行显示状态以及管理等。

1
2
3
4
5
6
7
8
9
spring:
application:
name: alibaba-sentinel
cloud:
sentinel:
transport:
dashboard: localhost:9899
server:
port: 8210
自定义埋点

所谓 “埋点” 我们可以理解为当用户访问特定的某个点,也就是监听这个点是否被用户所访问,在 Sentinel 中,我们可以通过 @SentinelResource 依赖中的埋点与 Sentinel 控制台中所增加的规则进行绑定,从而实现直接限流的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.demo.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 自定义埋点
*
* @author kunlun
* @date 2021/8/1
*/

@RestController
public class heyController {

@GetMapping("/hey")
@SentinelResource("hey")
public String hey() {
return "Server ok!";
}
}

当这完成之后,我们在 Sentinel 控制台中所增加的控流规则 QPS=1 当超过这个阀值的时候,该请求也会快速失败。

关联限流

关联限流简单理解就是,当我访问 test/one 的 QPS=1 的阀值过了以后,那么 test/two 这个接口就无法进行访问,因此我们在直接限流的基础上可以不需要设置埋点,直接添加两个接口即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 关联限流
*
* @author kunlun
* @date 2021/8/1
*/

@RestController
@RequestMapping("/test")
public class heyController {

@GetMapping("/one")
public String one() {
return "Server one ok!";
}

@GetMapping("/two")
public String two() {
return "Server two ok!";
}

}

链路限流


链路路由主要的作用就是,假设我们的接口都使用一个方法接口,那么在 Sentinel 中所填写的控流模式的入口资源,当入口资源超过 QPS 阀值时,那么将会被限流,但同样使用方法接口的另一个接口不会受此影响,为实现链路路由,我们需要添加如下依赖和增加配置:

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>

之后在配置文件中将是否统一网络上下文中选择 false:

1
2
3
4
5
6
7
8
9
10
spring:
application:
name: alibaba-sentinel
cloud:
sentinel:
transport:
dashboard: localhost:9899
web-context-unify: false
server:
port: 8210
server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.demo.server;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;

/**
* 服务接口
*
* @author kunlun
* @date 2021/8/1
*/
@Service
public class sentinelServer {

@SentinelResource("message")
public void sentinelTest() {
System.out.println("sentinel is Test.");
}
}
controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example.demo.controller;

import com.example.demo.server.sentinelServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 链路限流
*
* @author kunlun
* @date 2021/8/1
*/

@RestController
@RequestMapping("/test")
public class heyController {

@Autowired
private sentinelServer sentinelServer;

@GetMapping("/one")
public String one() {
sentinelServer.sentinelTest();
System.out.println("Server two ok!");
return "Server one ok!";
}

@GetMapping("/two")
public String two() {
sentinelServer.sentinelTest();
System.out.println("Server two ok!");
return "Server two ok!";
}

}

Warm Up

Warm Up 限流的主要作用就是为了应对猛烈的流量请求,分批次的进行处理,之后慢慢加流量,而不是向 DDos 一样直接就把服务干崩溃了。做一个很形象的比喻,我们吃饭的时候都是嚼了好几下才开始咽下去的,而一些猛人吃饭跟喝水一样,最终导致食物卡到了喉咙了,而这种情况在限流中也同样存在,因此 Warm Up 就很好的解决了这个问题。

排队限流

排队等待的限流模式主要通过超时时间,也就是每个请求的处理时常,以此让服务匀速处理请求而不是直接拒绝请求的作用,在新的控流规则中,我们设置 QPS 为 4,而超时时间(每个请求的处理时间为 1000ms),从而我们的服务性能可以处理,但如果超时时间设置为 100ms 时,则会发现被拦截的请求很多,这是因为服务的处理性能达不到预设的超时时间而造成的。

本文使用《江雪分析公开知识存储库知识共享许可证》进行发布